package org.kernely.stream.administration;

import java.util.HashSet;
import java.util.Set;

import org.kernely.security.persistence.Role;
import org.kernely.stream.StreamBundle;
import org.kernely.stream.dao.StreamDAO;
import org.kernely.stream.persistence.Stream;
import org.kernely.ui.MainApplication;
import org.kernely.ui.mvp.KernelyEvent;
import org.kernely.ui.mvp.KernelyEventReceiver;
import org.kernely.ui.mvp.KernelyPresenter;
import org.kernely.ui.utils.KernelyDialogWindow;
import org.kernely.ui.utils.KernelyNotification;

import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.terminal.ExternalResource;
import com.vaadin.ui.Button;
import com.vaadin.ui.Layout;
import com.vaadin.ui.Window;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Window.Notification;

public class StreamAdministrationPresenter extends KernelyPresenter<StreamAdministrationView> implements KernelyEventReceiver{

	private Window subwindow;
	private Button.ClickListener unlockListener;
	private Button.ClickListener lockListener;
	private KernelyDialogWindow confirmWindow;

	/**
	 * @see org.kernely.ui.mvp.KernelyPresenter#bind()
	 */
	@Override
	public final void bind() {
		listStreams();
		
		// Add a listener to the table
		this.view.getStreamTable().addListener(new Property.ValueChangeListener() {
			/**
			 * The method called when a user select an item in the table.
			 */
			public void valueChange(ValueChangeEvent event) {
				toggleStateButtons();
			}
		});

		// Add a listener to the add button
		this.view.getAddButton().addListener(new Button.ClickListener() {
			/**
			 * Action when the button is clicked
			 */
			public void buttonClick(ClickEvent event) {
				if(!StreamBundle.getSecurityService().currentUserHasOneOf(Role.ROLE_ADMINISTRATOR)){
					view.getWindow().showNotification("Error", "You are not administrator!", Notification.TYPE_ERROR_MESSAGE);
				}
				else{
					displayAddEditStreamWindow(false);
				}
			}
		});

		// Add a listener to the edit button
		this.view.getEditButton().addListener(new Button.ClickListener() {
			/**
			 * Action when the button is clicked
			 */
			public void buttonClick(ClickEvent event) {
				if(!StreamBundle.getSecurityService().currentUserHasOneOf(Role.ROLE_ADMINISTRATOR)){
					view.getWindow().showNotification("Error", "You are not administrator!", Notification.TYPE_ERROR_MESSAGE);
				}
				else{
					displayAddEditStreamWindow(true);
				}
			}
		});

		// Create a listener for the click on the disable button.
		lockListener = new ClickListener() {
			/**
			 * @see com.vaadin.ui.Button.ClickListener#buttonClick(com.vaadin.ui.Button.ClickEvent)
			 */
			public void buttonClick(ClickEvent event) {
				if(!StreamBundle.getSecurityService().currentUserHasOneOf(Role.ROLE_ADMINISTRATOR)){
					view.getWindow().showNotification("Error", "You are not administrator!", Notification.TYPE_ERROR_MESSAGE);
				}
				else{
					showLockUnlockWindow(false);
				}
			}
		};

		// Create a listener for the click on the enable button.
		unlockListener = new ClickListener() {
			/**
			 * @see com.vaadin.ui.Button.ClickListener#buttonClick(com.vaadin.ui.Button.ClickEvent)
			 */
			public void buttonClick(ClickEvent event) {
				if(!StreamBundle.getSecurityService().currentUserHasOneOf(Role.ROLE_ADMINISTRATOR)){
					view.getWindow().showNotification("Error", "You are not administrator!", Notification.TYPE_ERROR_MESSAGE);
				}
				else{
					showLockUnlockWindow(true);
				}
			}
		};
	}

	/**
	 * Change the state of the edit and enable/disable buttons.
	 * If nothing is selected in the table, disable the Edit and Enable/Disable buttons.
	 * If a line is selected, buttons are enabled.
	 */
	protected final void toggleStateButtons() {
		if (view.getStreamTable().getValue() == null){
			view.getEditButton().setEnabled(false);
			view.getDeleteButton().setEnabled(false);
			view.getLockButton().setEnabled(false);
			view.getLockButton().setCaption("Lock / Unlock");
		} else {
			view.getEditButton().setEnabled(true);
			view.getLockButton().setEnabled(true);
			view.getDeleteButton().setEnabled(true);

			//Change the text and the function of the Disable/Enable button
			StreamDAO sdao = StreamDAO.getInstance();
			Stream s = sdao.findStreamById((Integer)view.getStreamTable().getValue());

			// If the stream is unlocked, the state button is a lock button.
			if (s.getLocked() == 0){
				view.getLockButton().setCaption("Lock a stream");
				// We remove all listeners...
				view.getLockButton().removeListener(lockListener);
				view.getLockButton().removeListener(unlockListener);

				// And add the disable listener.
				view.getLockButton().addListener(lockListener);
			}
			// If the user is disabled, the state button is an enable button.
			else {
				view.getLockButton().setCaption("Unlock a stream");				
				// We remove all listeners...
				view.getLockButton().removeListener(lockListener);
				view.getLockButton().removeListener(unlockListener);

				// And add the enable listener.
				view.getLockButton().addListener(unlockListener);
			}
		}
	}

	/**
	 * Add all registered streams into the table
	 */
	private void listStreams(){
		// Only administrators can view users'list
		if(StreamBundle.getSecurityService().currentUserHasOneOf(Role.ROLE_ADMINISTRATOR)){
			// Reset the table
			view.getStreamTable().removeAllItems();

			StreamDAO sdao = StreamDAO.getInstance();
			Set<Stream> streams = new HashSet<Stream>(sdao.getAllStream());
			for(Stream s : streams){
				// We don't display users streams
				if (! s.getCategory().equals(Stream.CATEGORY_USERS)){
					// Is the user enabled ?
					String locked = "";
					if(s.getLocked() == 1){
						locked = "Yes";
					}
					else{
						locked = "No";
					}
					// Fill the table
					Object o = this.view.getStreamTable().addItem(new Object[] {
							s.getTitle(),
							s.getMessages().size(),
							s.getSubscriptors().size(),
							s.getRedactors().size(),
							locked}, s.getId());

					//
					if(s.getLocked() == 1){
						this.view.getStreamTable().setItemIcon(o,new ExternalResource("streambundle/images/locked.png"));
					} else {
						this.view.getStreamTable().setItemIcon(o,null);
					}
				}
			}
			view.getStreamTable().sort();
		}
	}

	private void showLockUnlockWindow(boolean enable){
		final boolean en = enable;

		// Get the user
		StreamDAO sdao = StreamDAO.getInstance();
		Stream stream = sdao.findStreamById((Integer)view.getStreamTable().getValue());

		// Confirm window
		if (enable){
			confirmWindow = new KernelyDialogWindow("Kernely - Unlock stream", "Do you really want to unlock " + stream.getTitle() + "?", KernelyDialogWindow.WARNING_ICON);			
		} else {
			confirmWindow = new KernelyDialogWindow("Kernely - Lock stream", "Do you really want to lock " + stream.getTitle() + "?", KernelyDialogWindow.WARNING_ICON);

		}
		confirmWindow.setConfirmButtonCaption("Yes");
		confirmWindow.setCancelButtonCaption("No");
		// Adding listeners on window's "confirm" buttons click
		confirmWindow.getConfirmButton().addListener(new Button.ClickListener() {
			/**
			 * @see com.vaadin.ui.Button.ClickListener#buttonClick(com.vaadin.ui.Button.ClickEvent)
			 */
			public void buttonClick(ClickEvent event) {
				lockStream(en);
			}
		});
		view.getWindow().addWindow(confirmWindow);
	}

	private void lockStream(boolean locked){
		StreamDAO sdao = StreamDAO.getInstance();
		Stream stream = sdao.findStreamById((Integer)view.getStreamTable().getValue());

		String state = null;

		// Change user's state in the database
		if (locked){
			stream.setLocked(0);
			state = "unlocked";
		} else {
			stream.setLocked(1);
			state = "locked";
		}

		sdao.updateStream(stream);

		// Remove the confirm window
		view.getWindow().removeWindow(confirmWindow);

		//Inform the user
		view.getWindow().showNotification(new KernelyNotification("Stream " + stream.getTitle() + " is now "+ state, KernelyNotification.INFO_ICON));

		//Refresh the table
		listStreams();

	}

	private void displayAddEditStreamWindow(boolean editMode){
		StreamBundle.getEventBus().addListener(this);
		StreamManagementWindowPresenter smwp = null;
		StreamManagementWindowView smwv;
		if (editMode){
			StreamDAO uddao = StreamDAO.getInstance();
			subwindow = new Window("Kernely - Edit an user ");
			smwp = new StreamManagementWindowPresenter(uddao.findStreamById((Integer)view.getStreamTable().getValue()));
		} else {
			subwindow = new Window("Kernely - Add an user ");
			smwp = new StreamManagementWindowPresenter();

		}
		subwindow.setModal(true);
		subwindow.setResizable(false);
		view.getWindow().addWindow(subwindow);
		subwindow.getContent().setSizeUndefined();
		smwv = new StreamManagementWindowView();
		smwp.setView(smwv);
		subwindow.setContent((Layout)smwp.getView());
		subwindow.setIcon(new ExternalResource("streambundle/images/stream_16*16.png"));
	}

	/**
	 * Method called when events are broadcast in the Kernely event bus.
	 */
	public final void handleKernelyEvent(KernelyEvent event) {
		if(event instanceof ManagementStreamEvent){
			listStreams();
		}

	}
	
	/**
	 * Called when the presenter is unset from UI.
	 */
	public final void unset() {
		StreamBundle.getEventBus().removeListener(this);
	}

}
